package pers.cz.javacvdemo.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import pers.cz.javacvdemo.video.Resolution;
import pers.cz.javacvdemo.video.VideoResolutionTransform;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;

/**
 * @version 1.0
 * @description:
 * @author: ChengZhi 0336
 * @create: 2025-08-15 14:29
 **/
@Slf4j
public class HlsUtils {

	public static FFmpegFrameRecorder createRecorder(String sourceObjectNamePrefix, String outputFilePath, FFmpegFrameGrabber grabber, int imageWidth, int imageHeight) {
		String outFilePathTemp = outputFilePath;
		outputFilePath = outputFilePath + "\\" + sourceObjectNamePrefix + "_" + imageWidth + "x" + imageHeight + ".m3u8";
		FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFilePath,
				imageWidth,
				imageHeight);
		log.info("文件路径：" + outputFilePath);
		// 基本配置
		recorder.setFormat("hls");

		// 视频配置
		recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
		recorder.setVideoBitrate(grabber.getVideoBitrate());
		recorder.setFrameRate(grabber.getVideoFrameRate());
		recorder.setGopSize((int) grabber.getVideoFrameRate());
		recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);

		// 编码器优化配置
		recorder.setOption("preset", "fast");
		recorder.setOption("tune", "zerolatency");
		recorder.setOption("profile", "baseline");
		recorder.setOption("level", "3.1");

		// 音频配置 - 使用正确的方法
		if (grabber.getAudioChannels() > 0) {
			recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
			recorder.setAudioChannels(grabber.getAudioChannels());
			recorder.setAudioBitrate(grabber.getAudioBitrate());

			// 使用 setAudioOption 设置采样率
			recorder.setAudioOption("ar", String.valueOf(grabber.getSampleRate()));

			// 设置音频质量
			recorder.setAudioQuality(0); // 最高质量
		}

		// HLS配置
		recorder.setOption("hls_time", "1");         // "10" 表示每个分片文件包含10秒的视频内容
		recorder.setOption("hls_list_size", "0");     // 播放列表中保留的分片数量"0" 表示保留所有分片（无限制）
		recorder.setOption("hls_wrap", "0");          // 分片文件编号是否循环, "0" 表示不循环 (默认) "1" 表示循环，分片编号会重新开始
		recorder.setOption("hls_flags", "delete_segments"); // "delete_segments"：删除旧的分片文件  "independent_segments"：每个分片独立 "discont_start"：不连续开始
		recorder.setOption("hls_segment_filename", outFilePathTemp + "\\" + imageWidth + "x" + imageHeight + "_segment_%03d.ts");

		// 其他优化配置
		recorder.setOption("g", "60");
		recorder.setOption("keyint_min", "30");
		recorder.setOption("sc_threshold", "0");

		return recorder;
	}

	public static void processVideoWithFFmpeg(String sourceObjectName, InputStream inputStream, List<Resolution> resolutions) {
		Path tempFile = null;
		try {
			int lastDotIndex = sourceObjectName.lastIndexOf('.');
			if (lastDotIndex == -1) {
				throw new IllegalArgumentException("文件名格式不正确，缺少后缀");
			}
			String prefix = sourceObjectName.substring(0, lastDotIndex);
			String suffix = sourceObjectName.substring(lastDotIndex);
			// 创建临时文件
			tempFile = Files.createTempFile(prefix, suffix);
			Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);

			List<FFmpegFrameRecorder> lists = new ArrayList<>();
			try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(tempFile.toString());) {
				grabber.start();
				Path outputFilePath = FileUtils.getTempDirectory().toPath();
				for (Resolution resolution : resolutions) {
					FFmpegFrameRecorder recorder = createRecorder(prefix, outputFilePath.toString(), grabber, resolution.getWidth(), resolution.getHeight());
					lists.add(recorder);
				}
			}
			VideoResolutionTransform videoResolutionTransform = new VideoResolutionTransform();
			videoResolutionTransform.execTransform(lists, tempFile);
		} catch (Exception e) {
			log.error("处理视频失败", e);
			throw new RuntimeException("处理视频失败", e);
		} finally {
			// 删除临时文件
			if (tempFile != null) {
				try {
					Files.deleteIfExists(tempFile);
				} catch (Exception e) {
					log.error("删除临时文件失败", e);
				}
			}
		}
	}
}
